#!/usr/bin/python

import os, sys, thread, threading, time, commands, random
from threading import Thread
from subprocess import Popen, PIPE

class cliui_pyukebox:
	def __init__(self):
		if __debug__:
			print "loading...."
		self.result = ("initial", 1)
		self.e = ''
		self.keepPlayLoop = True
		self.playlist = []
		self.defaultPlayListFile = "playlist.txt"
		self.loadPlayList(self.defaultPlayListFile)
		self.playlistCount = len(self.playlist)
		self.playListPosition = 0
		self.playRandom = False
		self.showFile = True 
		self.os = os.name	
		if __debug__:
			print "play list loaded.  Playlist count = " + str(self.playlistCount)
			
		if __debug__:
			print "start mplayer machine"
		self.mplayerthread = TheMPlayerMachine()
		self.mplayerthread.start()
		
		self.playNext(0)
		
		if __debug__:
			print "start keep alive"
		self.keepPlaying = threading.Thread( target=self.keepTheMusicPlaying)
		self.keepPlaying.setDaemon(True)
		self.keepPlaying.start()
	def mainLoop(self):
		print "welcome to the pyukebox where you can binge on music while purging the GUI!"
		print ""
		print "(type h for a list of commands)"
		print ""
		self.a = 1
		while self.a == 1:
			self.userInput = raw_input("user input:")
			self.result = self.processInput(self.userInput)
			print self.result[0]
			self.a = self.result[1]
		# clean up processes and threads
		self.keepPlayLoop = False
		#self.mplayerthread.stopPlaying()
		self.mplayerthread.stopThread()
	def loadPlayList(self, filename):
		afile = open(filename, 'r')
		filelines = afile.readlines()
		afile.close()
		for line in filelines:
			if len(line) > 2:
				#convert \ to /
				line = line.replace("\\", "/")	
				line = line.replace('\r\n', "")
				line = line.replace('\r', "")
				line = line.replace('\n', "")
				
				self.playlist.append(line)
		if __debug__:
			print "playlist loaded."
			print "items in playlist are:"
			for line in self.playlist:
				print line
	def stripDemSlashes(self,filePath):
		## this should be simpler
		return os.path.basename(filePath)
			
	def playNext(self,stop):
		if stop == 1:
			self.playStop()
		if self.playRandom:
			self.playListPosition = random.randint(0, self.playlistCount - 1)
		else:
			self.playListPosition += 1
			if self.playListPosition > self.playlistCount - 1:
				self.playListPosition = 0
			
		if self.showFile:
			self.whatIsPlaying = self.stripDemSlashes(str(self.playlist[self.playListPosition]))
			print "Now Playing: " + self.whatIsPlaying
	
		self.mplayerthread.playFile(self.playlist[self.playListPosition])
		 
	def playBack(self):
		self.playStop()
		if self.playRandom:
			self.playListPosition = random.randint(0, self.playlistCount - 1)
		else:
			self.playListPosition -= 1
			if self.playListPosition < 0:
				self.playListPosition = self.playlistCount - 1
		if self.showFile:
			self.whatIsPlaying = self.stripDemSlashes(str(self.playlist[self.playListPosition]))
                        print "Now Playing: " + self.whatIsPlaying

		self.mplayerthread.playFile(self.playlist[self.playListPosition])
		
	def playStop(self):
		self.mplayerthread.stopPlaying()
	def processInput(self,input):
		if input == "n":
			self.whatHappens = [" ", 1]
			self.playNext(1)
		elif input == "p":
			self.whatHappens = [" ", 1]
			self.playBack()
		elif input == "list":
			self.whatHappens = ["the list of songs in the playlist", 1]
			for line in self.playlist:
				print line
			print "total items: " + str(len(self.playlist))
		elif input == "show":
			self.whatHappens = ["toggle show file mode", 1]
			if self.showFile == True:
				self.showFile = False
				print "show file = False"
			else:
				self.showFile = True
				print "show file = True"
			print str(self.mplayerthread.getCurrentFile())
		elif input == "random":
			self.whatHappens = ["toggle playlist random", 1]
			if self.playRandom == True:
				self.playRandom == False
				print "random = False"
			else:
				self.playRandom = True
				print "random = True"
		elif input == "q":
			self.whatHappens = ["goodbye!", 0]
			self.playStop()
		elif input == "h":
			self.whatHappens = ["n: next song, p: previous song, q: quit pyukebox, h: help", 1]
		else:
			self.whatHappens = ["um yeah, that isn't a recognized command try hitting h for help", 1]
		
		return self.whatHappens
	def keepTheMusicPlaying(self):
		while self.keepPlayLoop:
			time.sleep(1.0)
			#print str(self.mplayerthread.donePlaying())
			if self.mplayerthread.donePlaying() and self.result[1] == 1:
				self.playNext(0)
	
	
class TheMPlayerMachine(Thread):
	def __init__(self):
		Thread.__init__(self)
		self.mplayerProcess = None
		self.pid = ""
		self.keeprunning = True
		self.pollresult = False
		self.os = os.name
		self.currentFile = ""
	def getCurrentFile(self):
		return self.currentFile
	def donePlaying(self):
		
		#try:
		#print "poll is " + str(self.mplayerProcess.poll())
		if self.mplayerProcess.poll() == None: ## removed to allow continual playback # or self.mplayerProcess.poll() == 0:
		#	print "return False"
			return False
		else:
		#	print "return True"
			return True
		#except:
		#print "return True"
		return True
	def playFile(self, theFile):
		self.currentFile = theFile
		
		if self.os == 'posix':
			if __debug__:
				print "start linux process"
			self.mplayerProcess = Popen('mplayer -quiet "' + str(theFile) + '"', stdout=PIPE, stdin=PIPE, stderr=PIPE, shell=True)
		else:
			if __debug__:
				print "start windows process"
			self.mplayerProcess = Popen('mplayer "' + str(theFile) + '"', stdout=PIPE, stdin=PIPE, stderr=PIPE)
			
		self.pid = self.mplayerProcess.pid
	def stopPlaying(self):
		if __debug__:
			print '### kill mplayer ###'
		try:
			
			#print 'kill -9 ' + str(self.mplayerProcess.pid)
			#print 'taskkill /F /PID ' + str(self.mplayerProcess.pid)
			
			#this is an inefficient play to do this...fix it
			#print self.os
			if self.os == 'posix':
				if __debug__:
					print "kill linux process"
				goawayl = os.popen('kill -9 `ps --ppid ' + str(self.pid) + ' -o pid=`')
				
			else:
				if __debug__:
					print "kill windows process"
					
				goawayw = os.popen('taskkill /F /PID ' + str(self.mplayerProcess.pid))
			
			
		except:
			if __debug__:
				print ""
				print "DEBUG: can't kill which means there is either nothing to kill"
				print "DEBUG: or you are just plain out of luck"
				print ""
			
			
	def stopThread(self):
		self.keeprunning = False
	def run(self):
		while self.keeprunning:
			time.sleep(0.2)
			


ui = cliui_pyukebox()
ui.mainLoop()	
